<?php
/**
 * 功能函数
 * Created by PhpStorm.
 * User: mUsr
 * Date: 18/6/27
 * Time: 下午5:02
 */


/**
 * 读取行情数据
 * @param $my_conn mysql连接实例
 * @param $begin_date 行情开始日期
 * @param $end_date 行情结束日期
 * @param $begin_time 分表开始时间
 * @param $end_time 分表结束时间
 * @param $rtType 实时类型
 * @param $rtSegment 实时时段
 * @param $rtInterval 实时间隔
 * @return array 以股票代码为键的数组，存放的是每支股票的行情数据
 */
function stock_quote($my_conn, $begin_date, $end_date, $begin_time, $end_time, $rtType = null, $rtSegment = null, $rtInterval = null)
{
    global $stock; // 股票基本信息
    $data = array(); // 重新组织后的行情数据，多维数组，以股票代码为键，以每条行情记录为子数组

    $where = '';
    if ($rtType) {
        $where .= " and Rt_Type = {$rtType}";
    }
    // 实时行情必须判断实时时段与实时间隔
    if ($rtType == 2) {
        if (is_null($rtSegment) || is_null($rtInterval)) {
            return;
        }
        $where .= "  and Rt_Segment = {$rtSegment} and Rt_Interval = {$rtInterval}";
    }

    // 循环读取开始时间到结束时间的行情分表
    $date = date('Y-m', strtotime($begin_time)); // 当前分表年月
    while (strtotime($date) <= strtotime(date('Y-m', strtotime($end_time)))) {
        $c_time_start = getCurrentTime();
        // 读取当前年月的分表数据
        $dateStr = str_replace("-", "", $date); // 把当前年月转换成和分表后缀一致
        $date = date('Y-m', strtotime('+1 month', strtotime($date))); // 下次循环中的月份
        // 检查行情表是否存在
        $sql = "SHOW TABLES LIKE 'stock_quote_{$dateStr}'";
        $res = $my_conn->query($sql);
        if (!$res->num_rows) {
            continue;
        }

        $sql = "select Stock_Code, Stock_Price as price, Stock_Close_Price as close, Stock_Date as date, Stock_Time, 
Rt_Type, Rt_Segment, Rt_Interval from stock_quote_{$dateStr} where Stock_Date >= '{$begin_date}' 
and Stock_Date <= '{$end_date}' {$where} order by Stock_Date,Rt_Segment,Rt_Interval";
//        $sql = "select Stock_Code, Stock_Price as price, Stock_Close_Price as close, Stock_Date as date, Stock_Time,
//Rt_Type, Rt_Segment, Rt_Interval from stock_quote_{$dateStr} where Stock_Date >= '{$begin_date}'
//and Stock_Date <= '{$end_date}' {$where} and Stock_Code = '000727' order by Stock_Date,Rt_Segment,Rt_Interval"; // todo debug
        $res = $my_conn->query($sql);
        if (!$res) {
            continue;
        }

        while ($row = mysqli_fetch_assoc($res)) {
            // 跳过基本信息不全的股票
            if (!isset($stock[$row['Stock_Code']])) {
                continue;
            }
            $stock2 = $stock[$row['Stock_Code']];
            if (is_null($stock2['m']) || is_null($stock2['xm']) || is_null($stock2['s']) || is_null($stock2['l']) || is_null($stock2['x']) || is_null($stock2['xx'])) {
                continue;
            }
            $data[$row['Stock_Code']][] = $row; // 把每条记录压入以股票代码为键的数组
        }
        echo "表{$dateStr}数据读取完成，用时：" . (getCurrentTime() - $c_time_start) . "秒\n";
        stat_broadcast("表{$dateStr}数据读取完成，用时：" . (getCurrentTime() - $c_time_start) . "秒");
    }

    return $data;
}


/**
 * 更新mongoDB中的行权数据，并输出行权数据
 * @param $my_conn mysql连接实例
 * @param $mongo mongodb连接实例
 * @return array 行权记录数据，以股票代码为键的关联数组
 */
function re_exright($my_conn, $mongo)
{
    // 读取行权记录，整理成以股票代码为键的数组
    $data = array();
    $sql = "select Stock_Code, Exright_Date, Exright_Type, Exright_Bonus, Exright_Present, Exright_Allotment, 
    Exright_Allotment_Price from stock_exright order by Exright_Date desc"; // 必须倒序行权日期，与复权算法一致
    $res = $my_conn->query($sql);
    while ($row = mysqli_fetch_assoc($res)) {
        $code = $row['Stock_Code'];
        unset($row['Stock_Code']);
        $data[$code][] = $row; // 把每条记录压入以股票代码为键的数组
    }

    // 更新mongoDB中的行权数据
    $collect = "Exright";
    $temp = array();
    $tmp = array();
    $collection = $mongo->stock->$collect;
    foreach ($data as $key => $value) {
        $collection->deleteOne(['_id' => $key]); // 删除旧的数据
        $temp['_id'] = $key;
        $temp['Exright'] = $value;
        $tmp[] = $temp;
    }
    $collection->insertMany($tmp);

    return $data;
}


/**
 * 获取某支股票的行权数据
 * @param $mongo mongodb连接实例
 * @param $code 股票代码
 * @return array 一支股票的行权数据
 */
function get_exright_one($mongo, $code)
{
    $collect = "Exright";
    $collection = $mongo->stock->$collect;
    $document = $collection->findOne(['_id' => $code]);
    $temp = array();
    foreach ($document['Exright'] as $value) {
        $tmp = array();
        foreach ($value as $key => $val) {
            $tmp[$key] = $val;
        }
        $temp[] = $tmp;
    }
    return $temp;
}


/**
 * 获取所有股票的行权数据
 * @param $mongo mongodb连接实例
 * @return array 所有股票的行权数据
 */
function get_exright($mongo)
{
    $collect = "Exright";
    $collection = $mongo->stock->$collect;
    $cursor = $collection->find();
    $data = array(); // 所有股票的数据
    foreach ($cursor as $item) {
        $k = $item['_id']; // 股票代码
        $temp = array(); // 每支股票的数据
        foreach ($item['Exright'] as $value) {
            $tmp = array(); // 每次行权数据
            foreach ($value as $key => $val) {
                $tmp[$key] = $val;
            }
            $temp[] = $tmp;
        }
        $data[$k] = $temp; // 以股票代码为键压入数组
    }
    return $data;
}


/**
 * 更新mongoDB中的股票基本信息，每次更新后必须重新初始化系统
 * @param $my_conn mysql连接实例
 * @param $mongo mongodb连接实例
 * @return array 以股票代码为键的数组
 */
function re_stock($my_conn, $mongo)
{
    // 读取基本信息，整理成以股票代码为键的数组
    $data = array();
    $sql = "select Stock_Code, Stock_Name, m, xm, s, l, x, xx from stock";
    $res = $my_conn->query($sql);
    while ($row = mysqli_fetch_assoc($res)) {
        $code = $row['Stock_Code'];
        unset($row['Stock_Code']);
        $data[$code] = $row; // 把每条记录压入以股票代码为键的数组
    }

    // 更新mongoDB中的基本信息
    $collect = "Stock";
    $tmp = array();
    $collection = $mongo->stock->$collect;
    foreach ($data as $key => $value) {
        $collection->deleteOne(['_id' => $key]); // 删除旧的数据
        $value['_id'] = $key;
        $tmp[] = $value;
    }
    $collection->insertMany($tmp);

    return $data;
}


/**
 * 输出买卖点数据到mysql
 * @param $my_conn
 * @param $data 买卖点数据
 * @param int $rt_type 实时类型
 * @param string $rt_segment 实时时段
 * @param string $rt_interval 实时间隔
 */
function buysell_to_mysql($my_conn, $data, $rt_type = 1, $rt_segment = 'null', $rt_interval = 'null')
{
    $tabel_name = 'stock_transact'; // 输出表名
    // 字段名：股票代码，价格，复权后价格，交易模式（1买入，2卖出），收益，收益比例，交易日期，实时类型（1历史，2实时），实时时段，实时间隔，创建时间
    $fields = 'Stock_Code, Stock_Price, Exright_Price, Transact_Mode, Transact_Profit, Transact_Rate, Transact_Date, 
    Rt_Type, Rt_Segment, Rt_Interval, Create_Time';

    $code = $data['_id']; // 股票代码
    $time = date('Y-m-d H:i:s'); // 创建时间
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            $transactProfit = isset($value['transactProfit']) ? $value['transactProfit'] : 'null'; // 收益
            $transactRate = isset($value['transactRate']) ? $value['transactRate'] : 'null'; // 收益率
            $val_str = "$code, {$value['price']}, {$value['exright']}, {$value['buy_sell']}, {$transactProfit}, {$transactRate}, '{$value['date']}', 
            $rt_type, $rt_segment, $rt_interval, '$time'";
            $sql = "insert {$tabel_name} ({$fields}) values ($val_str)";
            $my_conn->query($sql);
        }
    }
}


/**
 * 把实时行情数据转换成历史行情数据
 * @param $data 单支股票的行情数据，历史行情和实时行情
 * @return Generator 历史行情数据
 */
function to_history($data)
{
    $rt_temp = array(); // 实时行情临时数据，用于获取收盘价格

    foreach ($data as $row) {
        $history = array(); // 历史行情临时数据
        // 如果实时行情临时数组中的日期与当前日期不同，保存临时数据，作为上一交易日的收盘价格
        if ($rt_temp && $rt_temp['date'] != $row['date']) {
            $rt_temp['close'] = $rt_temp['price']; // 保存收盘价格
            $rt_temp['Rt_Type'] = 1; // 改为历史行情类型
            $history = $rt_temp; // 生成上一交易日的历史行情
        }
        // 保存实时行情数据到临时数组中
        if ($row['Rt_Type'] == 2) {
            $rt_temp = $row;
        } else {
            $history = $row; // 历史行情
            $rt_temp = array(); // 清空实时行情临时数据
        }

        if ($history) {
            yield $history; // 输出记录
        }
    }
}


/**
 * 读取文本文件中的历史行情数据
 * @param $dir 存放文件的目录
 * @param $code 股票代码
 * @return array 以日期为子键的二维数组
 */
function read_history($dir, $code)
{
    $file = "{$dir}SH#{$code}.txt"; // 查找以SH开头的
    if (!file_exists($file)) {
        $file = "{$dir}SZ#{$code}.txt"; // 查找以SZ开头的
        if (!file_exists($file)) {
            return;
        }
    }
    $handle = fopen($file, "r");
    $data = array();
    $temp = array();
    $i = 0;
    while (($row = fgetcsv($handle, 255, "\t")) !== FALSE) {
        $i++;
        if ($i <= 2) {
            continue; // 跳过前2行非数据行
        }
        $temp[] = $row;
    }
    array_pop($temp); // 删除最后一行非数据
    fclose($handle);

    foreach ($temp as $item) {
        $date_str = str_replace('/', '-', $item[0]); // 转换日期格式
        $data[$date_str]['Stock_Code'] = $code; // 股票代码
        $data[$date_str]['date'] = $date_str; // 行情日期
        $data[$date_str]['close'] = $item[4] * 10000; // 收盘价格
        $data[$date_str]['Rt_Type'] = 1; // 实时类型为1
    }

    return $data;
}
